package HomeWork;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * 贪吃蛇游戏主类（Swing GUI实现）
 *
 * 功能特性：
 * 1. 使用Swing Timer实现伪多线程游戏循环
 * 2. 支持方向控制（WASD）和快捷键操作
 * 3. 包含碰撞检测和得分系统
 * 4. 使用双缓冲技术消除画面闪烁
 * 5. 暂停/继续功能带对话框提示
 * 6. 渐变背景和动态颜色效果
 */
public class SnakeGame extends JFrame {

    // 游戏窗口尺寸常量
    private final int WIDTH = 800;          // 窗口宽度
    private final int HEIGHT = 600;         // 窗口高度
    private final int UNIT_SIZE = 20;       // 蛇身/苹果的单位尺寸（像素）
    private final int GAME_UNITS = (WIDTH * HEIGHT) / (UNIT_SIZE * UNIT_SIZE); // 游戏区域最大单位数
    private final int DELAY = 100;            // 游戏循环延迟(ms)，控制游戏速度

    // 游戏区域参数
    private final int MENU_HEIGHT = 30;      // 顶部菜单栏高度
    private final int GAME_AREA_Y = MENU_HEIGHT;  // 游戏区域起始Y坐标
    private final int GAME_AREA_HEIGHT = HEIGHT - MENU_HEIGHT; // 游戏区域可用高度

    // 游戏状态变量
    private final int[] x = new int[GAME_UNITS]; // 蛇身各段X坐标数组（最大长度由GAME_UNITS限制）
    private final int[] y = new int[GAME_UNITS]; // 蛇身各段Y坐标数组
    private int bodyParts = 3;          // 初始身体长度（3个单位）
    private int applesEaten = 0;        // 吃掉的苹果数（得分）
    private int appleX, appleY;         // 苹果坐标
    private char direction = 'R';       // 当前移动方向(U/D/L/R)，初始向右
    private boolean running = false;    // 游戏运行状态标志
    private boolean isPaused = false;   // 暂停状态标志
    private final Random random = new Random(); // 随机数生成器
    private Timer timer;                // 游戏循环定时器（核心多线程实现）

    // 双缓冲绘图相关
    private BufferedImage backBuffer;   // 后备缓冲区（用于消除画面闪烁）
    private Graphics2D backBufferGraphics; // 后备缓冲区绘图对象

    /**
     * 构造函数：初始化游戏窗口和组件
     */
    public SnakeGame() {
        // 窗口基础设置
        setTitle("贪吃蛇小游戏");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(WIDTH, HEIGHT);
        setLocationRelativeTo(null);  // 窗口居中
        setResizable(false);          // 禁止调整大小
        setFocusable(true);           // 可获取焦点

        // 初始化双缓冲系统
        backBuffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        backBufferGraphics = backBuffer.createGraphics();
        backBufferGraphics.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON  // 开启抗锯齿
        );

        // 创建自定义黑色菜单栏
        JMenuBar menuBar = new JMenuBar() {
            @Override
            public void paintComponent(Graphics g) { /* 禁用默认绘制 */ }
        };
        menuBar.setBackground(Color.BLACK);
        menuBar.setPreferredSize(new Dimension(WIDTH, MENU_HEIGHT));

        // 创建游戏菜单项
        JMenu gameMenu = new JMenu("游戏");
        gameMenu.setForeground(Color.WHITE);
        gameMenu.setFont(new Font("微软雅黑", Font.BOLD, 14));

        // 添加带快捷键的菜单项
        addMenuItem(gameMenu, "开始游戏  F2", KeyEvent.VK_F2, e -> startGame());
        addMenuItem(gameMenu, "暂停游戏  空格", KeyEvent.VK_SPACE, e -> togglePause());
        addMenuItem(gameMenu, "退出游戏  ESC", KeyEvent.VK_ESCAPE, e -> System.exit(0));

        menuBar.add(gameMenu);
        setJMenuBar(menuBar);

        // 键盘事件监听（方向控制）
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (!running) return;

                // 防止180度转向（如向右移动时不能直接向左）
                int key = e.getKeyCode();
                if (key == KeyEvent.VK_A && direction != 'R') direction = 'L';
                else if (key == KeyEvent.VK_D && direction != 'L') direction = 'R';
                else if (key == KeyEvent.VK_W && direction != 'D') direction = 'U';
                else if (key == KeyEvent.VK_S && direction != 'U') direction = 'D';
            }
        });

        requestFocusInWindow();
        setVisible(true);
    }

    /**
     * 辅助方法：创建带快捷键的菜单项
     */
    private void addMenuItem(JMenu menu, String text, int keyCode, ActionListener listener) {
        JMenuItem item = new JMenuItem(text);
        item.addActionListener(listener);
        item.setAccelerator(KeyStroke.getKeyStroke(keyCode, 0)); // 设置快捷键
        menu.add(item);
    }

    /**
     * 启动游戏（重置所有状态）
     */
    private void startGame() {
        if (running) return;

        // 重置游戏状态
        bodyParts = 3;
        applesEaten = 0;
        direction = 'R';
        running = true;
        isPaused = false;

        // 初始化蛇的位置（水平居中）
        for (int i = 0; i < bodyParts; i++) {
            x[i] = WIDTH/2 - UNIT_SIZE*i;
            y[i] = HEIGHT/2;
        }

        newApple();
        // 创建定时器（Swing Timer在事件分派线程中执行）
        timer = new Timer(DELAY, new GameLoop());
        timer.start(); // 启动游戏循环
    }

    /**
     * 暂停/恢复切换（带对话框提示）
     */
    private void togglePause() {
        if (!running) return;
        isPaused = !isPaused;

        if (isPaused) {
            timer.stop();
            // 弹出暂停提示窗口（模态对话框）
            JOptionPane.showMessageDialog(
                    this,
                    "游戏已暂停\n按空格键继续游戏",
                    "暂停提示",
                    JOptionPane.INFORMATION_MESSAGE
            );
        } else {
            timer.start();
        }
    }

    /**
     * 生成新苹果位置（随机且不在蛇身上）
     */
    private void newApple() {
        int maxX = (WIDTH - UNIT_SIZE) / UNIT_SIZE;
        int maxY = (GAME_AREA_HEIGHT - UNIT_SIZE) / UNIT_SIZE;
        appleX = random.nextInt(maxX) * UNIT_SIZE;
        appleY = random.nextInt(maxY) * UNIT_SIZE + GAME_AREA_Y;
    }

    /**
     * 检测苹果碰撞
     */
    private void checkApple() {
        Rectangle head = new Rectangle(x[0], y[0], UNIT_SIZE, UNIT_SIZE);
        Rectangle apple = new Rectangle(appleX, appleY, UNIT_SIZE, UNIT_SIZE);

        // 当蛇头与苹果发生碰撞时
        if (head.intersects(apple)) {
            applesEaten++;   // 得分增加
            bodyParts++;     // 身体长度+1
            newApple();      // 生成新苹果
        }
    }

    /**
     * 碰撞检测（边界和自身）
     */
    private void checkCollisions() {
        // 边界检测（游戏区域内部）
        if (x[0] < 0 || x[0] >= WIDTH - UNIT_SIZE ||
                y[0] < GAME_AREA_Y || y[0] >= GAME_AREA_Y + GAME_AREA_HEIGHT - UNIT_SIZE) {
            gameOver();
        }

        // 自身碰撞检测
        for (int i = bodyParts; i > 0; i--) {
            if (x[0] == x[i] && y[0] == y[i]) {
                gameOver();
                break;
            }
        }
    }

    /**
     * 游戏结束处理
     */
    private void gameOver() {
        running = false;
        timer.stop();
    }

    /**
     * 自定义绘图方法（使用双缓冲技术）
     */
    @Override
    public void paint(Graphics g) {
        // 双缓冲绘制流程
        if (running) {
            backBufferGraphics.setColor(Color.WHITE);
        } else {
            // 非运行状态使用渐变背景
            GradientPaint gradient = new GradientPaint(
                    0, 0, new Color(0, 100, 200),
                    WIDTH, HEIGHT, new Color(0, 200, 100)
            );
            backBufferGraphics.setPaint(gradient);
        }
        backBufferGraphics.fillRect(0, 0, WIDTH, HEIGHT);

        // 绘制游戏区域边框
        backBufferGraphics.setColor(new Color(40, 40, 40));
        backBufferGraphics.drawRect(0, GAME_AREA_Y, WIDTH-1, GAME_AREA_HEIGHT-1);

        if (running) {
            // 绘制苹果（红色主体+暗红边缘）
            backBufferGraphics.setColor(new Color(200, 50, 50));
            backBufferGraphics.fillOval(appleX + 2, appleY + 2, UNIT_SIZE, UNIT_SIZE);
            backBufferGraphics.setColor(Color.RED);
            backBufferGraphics.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);

            // 绘制蛇身（渐变颜色效果）
            for (int i = 0; i < bodyParts; i++) {
                float ratio = (float) i / bodyParts;
                Color color = new Color(
                        (int)(45 * (1 - ratio) + 0 * ratio),    // 红色分量
                        (int)(180 * (1 - ratio) + 200 * ratio), // 绿色分量
                        0                                       // 蓝色分量
                );
                backBufferGraphics.setColor(color);
                backBufferGraphics.fillRoundRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE, 5, 5);
            }

            // 绘制实时得分
            backBufferGraphics.setColor(Color.BLACK);
            backBufferGraphics.setFont(new Font("微软雅黑", Font.BOLD, 16));
            backBufferGraphics.drawString("得分: " + applesEaten, 15, MENU_HEIGHT - 8);

        } else {
            // 绘制游戏结束画面
            drawCenteredText("贪吃蛇小游戏", 56, new Color(255, 255, 255, 200), null);
            if (applesEaten > 0) {
                // 先绘制得分（上移）
                backBufferGraphics.setColor(Color.BLACK);
                backBufferGraphics.setFont(new Font("微软雅黑", Font.BOLD, 24));
                String scoreText = "最终得分: " + applesEaten;
                int textWidth = backBufferGraphics.getFontMetrics().stringWidth(scoreText);
                backBufferGraphics.drawString(scoreText, (WIDTH - textWidth)/2, HEIGHT/2 + 50);

                // 再绘制游戏结束提示（下移）
                backBufferGraphics.setColor(new Color(200, 50, 50));
                backBufferGraphics.setFont(new Font("微软雅黑", Font.BOLD, 48));
                String gameOverText = "游戏结束!";
                textWidth = backBufferGraphics.getFontMetrics().stringWidth(gameOverText);
                backBufferGraphics.drawString(gameOverText, (WIDTH - textWidth)/2, HEIGHT/2);
            }
        }

        // 将后备缓冲区绘制到屏幕
        g.drawImage(backBuffer, 0, 0, null);
    }

    /**
     * 辅助方法：绘制居中文本（带阴影效果）
     */
    private void drawCenteredText(String text, int fontSize, Color color, Color shadowColor) {
        backBufferGraphics.setFont(new Font("微软雅黑", Font.BOLD, fontSize));
        int textWidth = backBufferGraphics.getFontMetrics().stringWidth(text);

        if (shadowColor != null) {
            backBufferGraphics.setColor(shadowColor);
            backBufferGraphics.drawString(text, (WIDTH - textWidth)/2 + 3, HEIGHT/2 - 80 + 3);
        }

        backBufferGraphics.setColor(color);
        backBufferGraphics.drawString(text, (WIDTH - textWidth)/2, HEIGHT/2 - 80);
    }

    /**
     * 游戏循环实现（Swing Timer任务监听器）
     * 注意：这不是传统多线程，而是Swing的事件驱动模型
     * 优势：自动保证线程安全，无需处理同步问题
     */
    private class GameLoop implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (running && !isPaused) {
                // 1. 更新蛇身位置（数组拷贝实现蠕动效果）
                System.arraycopy(x, 0, x, 1, bodyParts);
                System.arraycopy(y, 0, y, 1, bodyParts);

                // 2. 根据方向更新蛇头位置
                switch (direction) {
                    case 'U' -> y[0] = Math.max(GAME_AREA_Y, y[0] - UNIT_SIZE);
                    case 'D' -> y[0] = Math.min(GAME_AREA_Y + GAME_AREA_HEIGHT - UNIT_SIZE, y[0] + UNIT_SIZE);
                    case 'L' -> x[0] = Math.max(0, x[0] - UNIT_SIZE);
                    case 'R' -> x[0] = Math.min(WIDTH - UNIT_SIZE, x[0] + UNIT_SIZE);
                }

                // 3. 执行碰撞检测
                checkApple();
                checkCollisions();
            }
            repaint(); // 触发界面重绘（EDT自动处理）
        }
    }

    /**
     * 程序入口点
     */
    public static void main(String[] args) {
        // 启用OpenGL硬件加速
        System.setProperty("sun.java2d.opengl", "True");
        // 使用Swing事件分派线程启动GUI
        SwingUtilities.invokeLater(() -> new SnakeGame().setVisible(true));
    }
}